#ifndef __CM_BASE_UDP_PORT_H__
#define __CM_BASE_UDP_PORT_H__

#include "Port.h"
#include "ByteBufferPool.h"
#include "Poco/NotificationQueue.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/IPAddress.h"
#include "Poco/Thread.h"
#include "Poco/Runnable.h"

using Poco::Thread;
using Poco::Runnable;
using Poco::NotificationQueue;
using Poco::Net::DatagramSocket;
using Poco::Net::ReadableNotification;
using Poco::Net::SocketReactor;
using Poco::Net::IPAddress;

namespace cm_base
{
    class UDPPort;

    class UDPPortListener
    {
    public:
        virtual void onReceive(UDPPort*p_port, ByteBuffer* p_data) =0;
    };

    class UDPPort: public Port, public Runnable
    {
    public:
        UDPPort(SocketReactor& reactor,ByteBufferPool* pool);
        virtual ~UDPPort();

        void registerListener(UDPPortListener* p_listner);
        
        //bind to ip 
        int setup(const IPAddress& ip);
        //bind to ip and port in sa
        int setup(const SocketAddress& sa);
        int teardown();

        //get the UDPPort's binded ip and port,
        //should be called after setup
        SocketAddress getHostAddress();

        int send(ByteBuffer* p_data,const SocketAddress& sa);
        void onReceive( ReadableNotification * p_rn);

        void run();

        enum{
            EVENT_RECVED_DATA ,
            EVENT_TO_SEND_DATA 
        };

    protected:
        NotificationQueue m_queue;

        ByteBufferPool* m_buffer_pool;

        SocketAddress m_hostAddress;

        DatagramSocket m_socket;
        SocketReactor& m_reactor;
        
        Thread m_thread;
        bool m_stop;

        UDPPortListener* m_listener;
    };
}//cm_base

#endif